package org.dreamwork.jasmine2.web.controls;

import org.dreamwork.jasmine2.events.EventException;
import org.dreamwork.jasmine2.util.WebControlCollection;
import org.dreamwork.jasmine2.util.DataContainer;
import org.dreamwork.jasmine2.web.IWebControl;
import org.dreamwork.jasmine2.web.IWebContainer;
import org.dreamwork.jasmine2.engine.IBindable;
import org.dreamwork.jasmine2.engine.IDataContainer;
import org.dreamwork.peony.DataBinder;
import org.apache.log4j.Logger;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: seth
 * Date: 2009-2-5
 * Time: 14:31:38
 */
public class Repeater extends WebContainer implements IDataContainer {
    private List data;

    private final static Logger logger = Logger.getLogger (Repeater.class);

    public Repeater () {
        viewStateEnabled = false;
    }

    public void onDataBind (Object sender) throws EventException {
        if (dataSource != null) {
            data = DataBinder.parseDataSource (dataSource, dataMember);
        }

        DataContainer container = new DataContainer ();
        if (page.container != null) {
            container.parent = page.container;
            page.stack.push (page.container);
        }
        page.container = container;

        createChildControls ();

/*
        page.dataIndex = 0;
        page.dataItem = null;
*/
        if (viewStateEnabled)
            stateManager.put ("data", data);
        if (!page.stack.isEmpty ()) page.container = page.stack.pop ();
        else page.container = null;
    }

    public void createChildControls () {
        WebControlCollection backup = new WebControlCollection ();

        for (int i = 0; i < childControls.size (); i++) {
            IWebControl control = childControls.getControl (i);
            backup.add (control.getId (), control);
        }
        childControls.clear ();

        if (data != null) for (int k = 0; k < data.size (); k ++ ) {
            page.container.dataItem = data.get (k);
            page.container.dataIndex = k;
            for (int i = 0; i < backup.count (); i++) {
                try {
                    bindControl (this, backup.getControl (i));
                } catch (Throwable t) {
                    logger.warn (t.getMessage (), t);
                    throw new RuntimeException (t);
                }
            }
        }
        childControlCreated = true;
    }

    @Override
    public IWebControl copy () {
        Repeater repeater = new Repeater ();
        repeater.setId ("__copied_repeater");
        repeater.addDataBindEvent (repeater);
        repeater.addPreRenderEvent (repeater);
        repeater.page = page;
        for (Iterator iter = getAttributeNames (); iter.hasNext ();) {
            String attrName = (String) iter.next ();
            String value = getAttribute (attrName);
            repeater.setAttribute (attrName, value);
        }
        for (Iterator iter = getDynamicAttributeNames (); iter.hasNext ();) {
            String attrName = (String) iter.next ();
            String expression = getDynamicAttribute (attrName);
            repeater.setDynamicAttribute (attrName, expression);
        }
        WebControlCollection wcc = (WebControlCollection) getChildControls ();
        for (int i = 0; i < wcc.count (); i ++) {
            IWebControl iwc = wcc.getControl (i);
            iwc.setPage (page);
            repeater.addControl (iwc);
        }
        return repeater;
    }

    private void bindControl (IWebContainer parent, IWebControl control) throws Throwable {
        IWebControl copy = null;
        if (control instanceof Repeater) {
            Repeater repeater = (Repeater) ((Repeater)control).copy ();
            repeater.dataBind ();
            for (int w = 0; w < repeater.getChildControls ().count (); w++) {
                IWebControl c = (IWebControl) repeater.getChildControls ().get (w);
                parent.addControl (c);
            }
        } else if (control instanceof IWebContainer) {
            IWebContainer container = (IWebContainer) control;
            IWebContainer ret = (IWebContainer) container.copy ();
            WebControlCollection child = (WebControlCollection) container.getChildControls ();
            for (int i = 0; i < child.count (); i++) {
                bindControl (ret, child.getControl (i));
            }
            copy = ret;
        } else if (control instanceof IBindable) {
            control = control.copy ();
            control.setClientId (control.getId () + "_" + page.container.dataIndex);
            ((IBindable) control).dataBind ();
            StringWriter sw = new StringWriter ();
            control.render (new PrintWriter (sw));
            copy = new Literal (sw.getBuffer ());
        } else {
            copy = control.copy ();
            copy.setId (control.getId () + "_" + page.container.dataIndex);
        }
        if (copy != null) {
            parent.addControl (copy);

            for (Iterator iter = copy.getDynamicAttributeNames (); iter.hasNext ();) {
                String attrName = (String) iter.next ();
                if (attrName.equalsIgnoreCase ("datasource")) continue;
                String expression = copy.getDynamicAttribute (attrName);
                Object value = page.eval (expression);
                copy.setAttribute (attrName, String.valueOf (value));
            }
        }
    }

    protected void loadViewState (Object savedState) throws IOException {
        stateManager.loadViewState (savedState);
        data = (List) stateManager.get ("data");
    }

    @Override
    protected void beginTag (PrintWriter writer) throws IOException {
        // do nothing
    }

    @Override
    protected void endTag (PrintWriter writer) {
        // do nothing
    }
}